package ch13.collecting;

import java.io.IOException;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class CollectingIntoMaps {
    public static void main(String[] args) throws IOException {
        var idToName = people().collect(
            Collectors.toMap(Person::id, Person::name)
        );
        System.out.println("idToName: " + idToName);

        var idToPerson = people().collect(
            Collectors.toMap(Person::id, Function.identity())
        );
        System.out.println("idToPerson: "
            + idToPerson.getClass().getName()
            + idToPerson
        );

        idToPerson = people().collect(
            Collectors.toMap(
                Person::id,
                Function.identity(),
                // (existingValue, newValue) -> {}
                (_, _) -> { // Duplicate key
                    throw new IllegalStateException();
                },
                TreeMap::new
            )
        );
        System.out.println("idToPerson: "
            + idToPerson.getClass().getName()
            + idToPerson
        );

        Stream<Locale> locales = Stream.of(Locale.getAvailableLocales());
        var languageNames = locales.collect(
            Collectors.toMap(
                Locale::getDisplayLanguage,
                l -> l.getDisplayLanguage(),
                (existingValue, _) -> existingValue
          )
        );

        System.out.println();
        languageNames.forEach((k, v) -> System.out.println(k + ": " + v));
        // System.out.println("languageNames: " + languageNames);

        locales = Stream.of(Locale.getAvailableLocales());
        var countryLanguageSets = locales.collect(
            Collectors.toMap(
                Locale::getDisplayCountry,
                l -> Set.of(l.getDisplayLanguage()),
                (a, b) -> {
                    var union = new HashSet<>(a);
                    union.addAll(b);
                    return union;
                }
          )
        );
        // System.out.println("countryLanguageSets: " + countryLanguageSets);
        System.out.println();
        countryLanguageSets.forEach((country, languages) ->
            System.out.println(country + ": " + languages)
        );
    }

    public static Stream<Person> people() {
        return Stream.of(
                new Person(1001, "Peter"),
                new Person(1002, "Paul"),
                new Person(1003, "Mary")
        );
    }
}

record Person(int id, String name) {}
